package com.ztgf.logistics.service.deppon;

import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.baomidou.mybatisplus.mapper.Wrapper;
import com.baomidou.mybatisplus.plugins.Page;
import com.ztgf.common.constant.CommonParameter;
import com.ztgf.common.constant.Result;
import com.ztgf.common.constant.SysConstant;
import com.ztgf.common.enums.CodeEnum;
import com.ztgf.dubbo.exception.ServiceException;
import com.ztgf.common.utils.DateUtils;
import com.ztgf.common.vo.UserVO;
import com.ztgf.logistics.models.bo.deppon.LogisticsAuditBO;
import com.ztgf.logistics.models.bo.deppon.LogisticsUserBO;
import com.ztgf.logistics.models.dto.deppon.LogisticsBillDTO;
import com.ztgf.logistics.models.dto.deppon.LogisticsUserContractDTO;
import com.ztgf.logistics.models.service.deppon.ILogisticsUserContractService;
import com.ztgf.logistics.models.service.deppon.ILogisticsUserMoneyLogService;
import com.ztgf.logistics.models.vo.deppon.LogisticsUserVO;
import com.ztgf.order.models.vo.OrderSalesCategoryShopVO;
import com.ztgf.shopping.models.dto.audit.AuditDTO;
import com.ztgf.shopping.models.dto.shop.ShopInfoDTO;
import com.ztgf.shopping.models.service.shop.IShopInfoService;
import com.ztgf.sys.models.dto.SysUserDTO;
import com.ztgf.sys.models.service.ISessionService;
import com.ztgf.sys.models.service.ISysConfigService;
import lombok.extern.slf4j.Slf4j;
import org.apache.dubbo.config.annotation.DubboReference;
import org.apache.dubbo.config.annotation.DubboService;
import org.springframework.beans.BeanUtils;
import javax.annotation.Resource;
import com.ztgf.logistics.common.config.YmlConfig;
import com.baomidou.mybatisplus.service.impl.ServiceImpl;
import com.ztgf.logistics.mapper.deppon.LogisticsUserMapper;
import com.ztgf.logistics.models.service.deppon.ILogisticsUserService;
import com.ztgf.logistics.models.bo.deppon.LogisticsUserSaveBO;
import com.ztgf.logistics.models.dto.deppon.LogisticsUserDTO;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Comparator;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 物流用户信息表控制器
 *
 * @author mxli
 * @Date 2021-09-13 22:16:41
 */
@DubboService
@Slf4j
public class LogisticsUserServiceImpl extends ServiceImpl<LogisticsUserMapper, LogisticsUserDTO> implements ILogisticsUserService{

    @Resource
    private YmlConfig ymlConfig;
    @DubboReference
    private IShopInfoService shopInfoService;
    @DubboReference
    private ISysConfigService sysConfigService;
    @DubboReference
    private ISessionService sessionService;
    @Autowired
    private ILogisticsUserContractService logisticsUserContractService;
    @Autowired
    private ILogisticsUserMoneyLogService logisticsUserMoneyLogService;

    @Override
    public boolean add(LogisticsUserSaveBO saveBO) {
        LogisticsUserDTO dto = new LogisticsUserDTO();
        BeanUtils.copyProperties(saveBO,dto);
        Long id = ymlConfig.getPkId();
        dto.setId(id);
        return this.insert(dto);
    }

    @Override
    public Result insertApply(Long shopId) {
        ShopInfoDTO shopInfoDTO = shopInfoService.selectById(shopId);
        if(shopInfoDTO == null){
            return null;
        }

        UserVO userVO = sessionService.getUserVO();


        LogisticsUserDTO userDTO = this.selectById(shopId);
        if(userDTO == null){
            userDTO = new LogisticsUserDTO();
            userDTO.setId(shopId);
            userDTO.setCreateUserId(userVO.getId());
            userDTO.setCreateUserName(userVO.getName());
            Long selfShopId = sysConfigService.getLongByCode(SysConstant.SELF_OPERATED_SHOP_ID);
            if(shopId.equals(selfShopId)){
                userDTO.setType(2);
                userDTO.setContractStatus(1);
            } else {
                //保证金的
                BigDecimal mguaranteeMoneyQuota = sysConfigService.getBigDecimalByCode(SysConstant.MGUARANTEE_MONEY_QUOTA);
                //虚拟额度
                BigDecimal logisticsMoneyQuota = sysConfigService.getBigDecimalByCode(SysConstant.MGUARANTEE_MONEY_QUOTA);
                userDTO.setMguaranteeMoneyQuota(mguaranteeMoneyQuota);
                userDTO.setLogisticsMoneyQuota(logisticsMoneyQuota);
            }

            this.insert(userDTO);
        }

        if(userDTO.getContractStatus() == 0){
            Wrapper wrapper = new EntityWrapper();
            wrapper.eq("shop_id", shopId);
            wrapper.eq("status", 0);
            wrapper.last("limit 1");
            LogisticsUserContractDTO contractDTO = logisticsUserContractService.selectOne(wrapper);
            if(contractDTO == null){
                //创建合同
                contractDTO = new LogisticsUserContractDTO();
                contractDTO.setId(ymlConfig.getPkId());
                contractDTO.setCreateUserId(userVO.getId());
                contractDTO.setShopId(shopId);
                contractDTO.setTempletId(null);
                contractDTO.setTempletName(null);
                contractDTO.setContractId(null);
                contractDTO.setFileUrl(null);
                logisticsUserContractService.insert(contractDTO);
            }
        }
        return new Result();
    }

    /**
     * 修改用户金额，并添加日志
     * @param dto
     * @param oldDTO
     * @param logType 类型：0保证金缴纳、1保证金额退还、2扣除保证金、3设置保证金的、4设置月结用户额度、5物流下单金额（预付费）、6物流下单真实金额、7账单还款
     */
    @Override
    @Transactional(rollbackFor = ServiceException.class)
    public void updateMoney(Long businessId, LogisticsUserDTO dto, LogisticsUserDTO oldDTO, BigDecimal money, int logType, Long userId, String userName) {
        Wrapper wrapper = new EntityWrapper();
        wrapper.eq("id", oldDTO.getId());

        if(dto.getMguaranteeMoneyQuota() != null){
            wrapper.eq("mguarantee_money_quota", oldDTO.getMguaranteeMoneyQuota());
            wrapper.and(dto.getMguaranteeMoneyQuota() + " >= 0");
        }
        if(dto.getMguaranteeMoney() != null){
            wrapper.eq("mguarantee_money", oldDTO.getMguaranteeMoney());
            wrapper.and(dto.getMguaranteeMoney() + " >= 0");
        }
        if(dto.getLogisticsMoneyQuota() != null){
            wrapper.eq("logistics_money_quota", oldDTO.getLogisticsMoneyQuota());
            wrapper.and(dto.getLogisticsMoneyQuota() + " >= 0");
        }
        if(dto.getLogisticsMoneyUsed() != null){
            wrapper.eq("logistics_money_used", oldDTO.getLogisticsMoneyUsed());
            wrapper.and(dto.getLogisticsMoneyUsed() + " >= 0");
        }
        if(dto.getLogisticsMoneyUnused() != null){
            wrapper.eq("logistics_money_unused", oldDTO.getLogisticsMoneyUnused());
            wrapper.and(dto.getLogisticsMoneyUnused() + " >= 0");
        }
        if(dto.getLogisticsMoneyUsedScale() != null){
            wrapper.eq("logistics_money_used_scale", oldDTO.getLogisticsMoneyUsedScale());
            wrapper.and(dto.getLogisticsMoneyUsedScale() + " >= 0");
        }

        boolean flag = this.update(dto , wrapper);
        if(!flag){
            throw new ServiceException(CodeEnum.FAIL_100008);
        }

        BigDecimal mguaranteeMoneyQuota = dto.getMguaranteeMoneyQuota() == null ? oldDTO.getMguaranteeMoneyQuota() : dto.getMguaranteeMoneyQuota();
        BigDecimal mguaranteeMoney = dto.getMguaranteeMoney() == null ? oldDTO.getMguaranteeMoney() : dto.getMguaranteeMoney();
        BigDecimal logisticsMoneyQuota = dto.getLogisticsMoneyQuota() == null ? oldDTO.getLogisticsMoneyQuota() : dto.getLogisticsMoneyQuota();
        BigDecimal logisticsMoneyUsed = dto.getLogisticsMoneyUsed() == null ? oldDTO.getLogisticsMoneyUsed() : dto.getLogisticsMoneyUsed();
        BigDecimal logisticsMoneyUnused = dto.getLogisticsMoneyUnused() == null ? oldDTO.getLogisticsMoneyUnused() : dto.getLogisticsMoneyUnused();
        BigDecimal logisticsMoneyUsedScale = dto.getLogisticsMoneyUsedScale() == null ? oldDTO.getLogisticsMoneyUsedScale() : dto.getLogisticsMoneyUsedScale();
        //添加物流流水日志
        logisticsUserMoneyLogService.insert(businessId, oldDTO.getId(), logType, money,  mguaranteeMoneyQuota, mguaranteeMoney, logisticsMoneyQuota, logisticsMoneyUsed, logisticsMoneyUnused, logisticsMoneyUsedScale, userId, userName, CodeEnum.FAIL_100008);
    }

    /**
     * 修改物流信用金
     * @param shopId
     * @param money
     * @param userId
     * @param userName
     * @return
     */
    @Override
    public Result updateLogisticsMoneyQuota(Long businessId, Long shopId, BigDecimal money, Long userId, String userName) {
        LogisticsUserDTO dto = this.selectById(shopId);
        if(money == null || dto == null || money.compareTo(BigDecimal.ZERO) < 0){
            return new Result<>(CodeEnum.FAIL_100002);
        }
        LogisticsUserDTO newDTO = new LogisticsUserDTO();

        newDTO.setLogisticsMoneyQuota(money);
        BigDecimal usedMoney = dto.getLogisticsMoneyUsed();
        BigDecimal unusedMoney = money.subtract(usedMoney);
        BigDecimal moneyUsedScale = usedMoney.divide(money, 4).multiply(BigDecimal.valueOf(100));

        newDTO.setLogisticsMoneyUnused(unusedMoney);
        newDTO.setLogisticsMoneyUsedScale(moneyUsedScale);

        this.updateMoney(businessId, newDTO, dto, money, 4, userId, userName);

        return new Result<>();
    }

    @Override
    public Result<Page<LogisticsUserVO>> queryPageList(LogisticsUserBO bo) {

        Page<LogisticsUserVO> page = new Page<>(bo.getPageNo(), bo.getPageSize());

        List<LogisticsUserVO> list = this.baseMapper.queryPageList(bo);
        if (list!=null && list.size()>0){
            for (LogisticsUserVO logisticsUserVO : list) {
                EntityWrapper<LogisticsUserContractDTO> wrapper = new EntityWrapper<>();
                wrapper.eq("shop_id",logisticsUserVO.getId());
                wrapper.eq("status","1");
                wrapper.orderBy("create_time",false);
                LogisticsUserContractDTO logisticsUserContractDTO = logisticsUserContractService.selectOne(wrapper);
                if(logisticsUserContractDTO != null){
                    logisticsUserVO.setSignDate(logisticsUserContractDTO.getSignTime());
                    try {
                        int i = this.daysBetween(DateUtils.getCurrentDateTime(),logisticsUserContractDTO.getEndDate());

                        if (i<0){
                            logisticsUserVO.setFinalyDate(0);
                        }else {
                            logisticsUserVO.setFinalyDate(i);
                        }


                    } catch (ParseException e) {
                        e.printStackTrace();
                    }
                }
            }
            if(bo.getOrderByQuota()==null && bo.getOrderByQuotaUserScale()==null){
                list= list.stream().sorted(Comparator.comparing(LogisticsUserVO::getFinalyDate)).collect(Collectors.toList());
            }
            int count=0;
            if(list != null && list.size() > 0) {
                page.setTotal(list.size());
                count = list.size();
                int fromIndex = (bo.getPageNo()-1) * bo.getPageSize();
                int toIndex = bo.getPageNo() * bo.getPageSize();
                if (toIndex > count) {
                    toIndex = count;
                }
                List<LogisticsUserVO> list1 = list.subList(fromIndex, toIndex);
                page.setRecords(list1);

                return new Result<>(page);
            }
        }
        page.setRecords(list);
        return new Result<>(page);
    }
    public static int daysBetween(Date smdate, Date bdate) throws ParseException
    {
        SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd");
        smdate=sdf.parse(sdf.format(smdate));
        bdate=sdf.parse(sdf.format(bdate));
        Calendar cal = Calendar.getInstance();
        cal.setTime(smdate);
        long time1 = cal.getTimeInMillis();
        cal.setTime(bdate);
        long time2 = cal.getTimeInMillis();
        long between_days=(time2-time1)/(1000*3600*24);

        return Integer.parseInt(String.valueOf(between_days));
    }

    @Override
    public void saveAudit(LogisticsAuditBO auditBO) {
        LogisticsUserDTO newDTO = new LogisticsUserDTO();
        newDTO.setAuditId(auditBO.getAuditId());
        newDTO.setId(auditBO.getShopId());
        newDTO.setLogisticsMoneyQuota(auditBO.getLogisticsMoneyQuota());
        newDTO.setMguaranteeMoneyQuota(auditBO.getMguaranteeMoneyQuota());
        boolean flag = this.updateById(newDTO);
        if(!flag){
            throw new  ServiceException(CodeEnum.FAIL_100014);
        }
    }

}
